package cc.telecomdigital.tdstock.Framework;

import java.util.List;

import cc.telecomdigital.tdstock.Framework.Application_Framework.LS_ItemRequestType;
import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.Framework.UniqueItem.DisplayChangeListener.IDisplayOnOffChangeListener;
import cc.telecomdigital.tdstock.Framework.UniqueItem.PhoneIncomingCallListener.PHONE_STATE;
import cc.telecomdigital.tdstock.Framework.UniqueItem.ScreenOrientationChangeListener.IScreenOrientationChangeListener;
import cc.telecomdigital.tdstock.Framework.UniqueItem.UnLockScreenListener.IUnLockScreenListener;
import cc.telecomdigital.tdstock.Services.LS_SubscriptionItem;
import cc.telecomdigital.tdstock.Services.LS_UserClient.ILS_UserClient_ConnectionListener;
import cc.telecomdigital.tdstock.Services.LS_UserClient.ILS_UserClient_Response;
import cc.telecomdigital.tdstock.Framework.UniqueItem.NetworkChangeListener.INetworkChangeListener;
import cc.telecomdigital.tdstock.Tools.Abstract_ActivityController;
//import cc.telecomdigital.tdstock.Tools.ActivityGroupController;
import cc.telecomdigital.tdstock.Tools.ReporterTicker.IReporterTicker_Report;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
//import android.view.KeyEvent;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;

//Either ActivityController or ActivityGroupController
public abstract class Abstract_Activity_Framework<T extends Abstract_ActivityController>
		extends Activity
{
	static protected boolean			debugMode	= false;

	protected Context				actContext;
	protected boolean                  isUIActive;

	// The Class use control list and should have a host list to implement

	protected abstract T GetActivityController();

	protected T					_activityController	= null;
	protected Application_Framework	appHost;

	private String					className			= null;

	/** Identity of this module
	 * Get the ClassName of the object **/
	protected String GetIdentity()
	{
		if (className == null)
			className = getClass().getName();
		return className;
	}
	
	@Override
	protected void onCreate(Bundle iSaveInstance)
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onCreate");
			
		isUIActive = false;
		super.onCreate(iSaveInstance);				
		appHost = Application_Framework.GetInstance();
		_activityController = GetActivityController();
		actContext = this;
		//Flush what ever we java create on our LSClient, because the destroy does not call all the time
		LSClient_FlushSafe();
		displayObj = getWindowManager().getDefaultDisplay();
		UpdateDisplayDimension();		
	}
	
	@Override
	protected void onStart()
	{
		UpdateDisplayDimension();
		super.onStart();
	}

	static protected int	fScrWidthPixel		= 0;
	static protected int	fScrHeightPixel	= 0;
	static protected Display displayObj;
	/** Basically update system configuration **/
	protected void UpdateDisplayDimension()
	{
		fScrWidthPixel  = displayObj.getWidth();
		fScrHeightPixel = displayObj.getHeight();
	}

	/** Return the stored values;
	 *  The system will be constantly report to us
	 *  @return true for connected
	 */
	protected boolean IsNetworkAvailable()
	{
		return appHost.IsNetworkAvailable();
	}

	/** Check if the display is one 
	 *  @return true for display is on
	 */
	protected boolean IsDisplayOn()
	{
		return appHost.IsDisplayOn();
	}

	// Depend on Manifest
	@Override
	public void onConfigurationChanged(Configuration iNewChange)
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "onConfigurationChanged: " + iNewChange.toString());
		super.onConfigurationChanged(iNewChange);
		UpdateDisplayDimension();
	}

//	/** Happens when home key is pressed
//	    Detect by key press
//	    Version 1.5 supports or lower **/
//	private void onHomeKeyPressed()
//	{
//		appHost.onPauseAction();
//	}

	protected boolean subscribeOnResumeOpt = true;
	// On start work with non-UI stuff
	@Override
	protected void onResume()
	{	
		//Resume their stuff first
		super.onResume();	
		appHost.onResume();		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onResume");
		
		appHost.SetAsActiveActivity(this);
		RegisterAllItems();
		
		if (subscribeOnResumeOpt)
			appHost.LSClient_ResumeAllItems(getClass());

		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onResume Done");
		isUIActive = true;
	}

	// UI pause, pause is guarantee to be called, when lock screen is on, when activity will
	// be switched
	@Override
	protected void onPause()
	{
		isUIActive = false;
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onPause");

		UnregisterAllItems();
		
		/** If the finished option is set, then we let the finish to call the Un-subscribe
		 * else we should manually un-subscribe each time we are not using it */
		if (!_activityController.IsDestroyOnFinish())
			appHost.LSClient_UnsubscribeAllItems(getClass());
		else
		{
			/* This process takes quite long */
			appHost.LSClient_SuspendAllItems(getClass());
		}
		
		appHost.onPause();
		super.onPause();

		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onPause Done");
	}

	private void RegisterAllItems()
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "RegisterAllItems starts");
		
		if (this instanceof IScreenOrientationChangeListener)
			appHost.RegisterToListenScreenOrientationChange((IScreenOrientationChangeListener) this);
		
		if (this instanceof INetworkChangeListener)
			appHost.RegisterToListenNetworkChange((INetworkChangeListener) this);

		if (this instanceof IDisplayOnOffChangeListener)
			appHost.RegisterToListenDisplayChange((IDisplayOnOffChangeListener) this);

//		if (this instanceof IUnLockScreenListener)
//			appHost.RegisterToListenUnlockScreen((IUnLockScreenListener) this);
		
		// if it has interface for getting the data, then we will put register for receiving connection status
		if (this instanceof ILS_UserClient_Response)
		{
			appHost.RegisterToListenLSClientConnection((ILS_UserClient_ConnectionListener) this);
			appHost.RegisterToListenCDRChanges((IReporterTicker_Report) this);
		}
		else
		{
			if (this instanceof ILS_UserClient_ConnectionListener)
				appHost.RegisterToListenLSClientConnection((ILS_UserClient_ConnectionListener) this);

			if (this instanceof IReporterTicker_Report)
				appHost.RegisterToListenCDRChanges((IReporterTicker_Report) this);
		}
		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "RegisterAllItems end");		
	}	
	
	private void UnregisterAllItems()
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "UnregisterAllItems starts");
		
		// if it has interface for getting the data, then we will put unregister		
		if (this instanceof ILS_UserClient_Response)
		{
			appHost.UnregisterToListenLSClientConnection((ILS_UserClient_ConnectionListener) this);
			appHost.UnregisterToListenCDRChanges((IReporterTicker_Report) this);
		}
		else
		{
			if (this instanceof ILS_UserClient_ConnectionListener)
				appHost.UnregisterToListenLSClientConnection((ILS_UserClient_ConnectionListener) this);
			if (this instanceof IReporterTicker_Report)
				appHost.UnregisterToListenCDRChanges((IReporterTicker_Report) this);
		}

		if (this instanceof INetworkChangeListener)
			appHost.UnregisterToListenNetworkChange((INetworkChangeListener) this);

		if (this instanceof IDisplayOnOffChangeListener)
			appHost.UnregisterToListenDisplayChange((IDisplayOnOffChangeListener) this);

		if (this instanceof IScreenOrientationChangeListener)
			appHost.UnregisterToListenScreenOrientationChange((IScreenOrientationChangeListener) this);

//		if (this instanceof IUnLockScreenListener)
//			appHost.UnregisterToListenUnlockScreen((IUnLockScreenListener) this);		
		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "UnregisterAllItems End");		
	}

	//on stop mean the UI is no longer visible, could be in suspend state
	@Override
	protected void onStop()
	{
		isUIActive = false;
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onStop Starts");
			
		/** If the finished option is set, then we let the finish to call the Un-subscribe
		 * else we should manually un-subscribe each time we are not using it */
		if (!_activityController.IsDestroyOnFinish())
		{
			appHost.LSClient_UnsubscribeAllItems(getClass());
		}
		else
		{
			/* This process takes quite long */
			appHost.LSClient_SuspendAllItems(getClass());
		}
		
		//comment by haibo in 2011－11－03, to avoid  kill the app accidentally
/*		PHONE_STATE globalPhoneState;
		Activity  curActivity;
		
		globalPhoneState = appHost.GetCurrentPhoneState();
		curActivity = appHost.GetCurrentActivity();
		if ( (curActivity == null) || 
			(curActivity.equals(this) && (globalPhoneState == PHONE_STATE.IDLE)))
		{
			if (debugMode)
				TDStockLog.i(GetIdentity(), "No other focus on window, we are dismissing and phone are not being used");
			super.onStop();			
			appHost.Dismiss();
			return;
		}
*/		
		
		boolean     enterCondition;
		boolean     terminateApp;		
		Activity    curActivity;
		
		curActivity = appHost.GetCurrentActivity();
		
		enterCondition = false;
		terminateApp     = false;
		
		if (curActivity == null)
		{
			if (debugMode)
				TDStockLog.i(GetIdentity(), "onStop: CurActivity is null");
			enterCondition = true;
			terminateApp   = true;
		}
		else
		{
			if (appHost.AllowToTerminateApp() == true)
			{
				if (debugMode)
					TDStockLog.i(GetIdentity(), "onStop: Not App Exit Option");				
				if (curActivity.equals(this))
					enterCondition = true;
			}			
			else
			{
				if (debugMode)
					TDStockLog.i(GetIdentity(), "onStop: Looking for PhoneState");
				
				PHONE_STATE globalPhoneState;
				
				globalPhoneState = appHost.GetCurrentPhoneState();				
				if ((curActivity.equals(this) && (globalPhoneState == PHONE_STATE.IDLE)))
				{
					enterCondition = true;
					terminateApp = true;
				}
			}
		}
				
		if (enterCondition)
		{
			if (debugMode)
				TDStockLog.i(GetIdentity(), "OnStop: terminatingApp=" + terminateApp);
			
			if (terminateApp)
				appHost.Dismiss();
			else
				appHost.onSuspend();
		}
		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onStop Done");
		super.onStop();
	}

	@Override
	protected void onDestroy()
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onDestroy");

		//------ to avoid java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget-----modified by haibo, 2011-10-31
		try 
		{
			ViewGroup findGroup;
			View 	currentView;
			
			currentView = null;			
			findGroup = (ViewGroup)findViewById(android.R.id.content);
			if (findGroup != null)
			{
				if (findGroup.getChildCount() != 0)
					currentView = findGroup.getChildAt(0);
			}
			
			if (currentView != null)
				unbindDrawables(currentView);
				
			System.gc();				
		}
		catch (Exception e)
		{
			TDStockLog.e(GetIdentity(), e.toString());
			e.printStackTrace();
		}
		//------ to avoid java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget-----modified by haibo, 2011-10-31
		
		// This is to un-subscribe all items, not usually called, so a fail-safe case is to wipe of the
		// register when activity create
		appHost.LSClient_UnsubscribeAllItems(getClass());
		super.onDestroy();
	}
	
	/**
	 * modified by haibo, 2011-10-31
	 * to avoid java.lang.OutOfMemoryError: Bitmap Size Exceeds VM Budget
	 * 
	 * Reference:  http://stackoverflow.com/questions/1147172/what-android-tools-and-methods-work-best-to-find-memory-resource-leaks
	 * 
	 *  Reference:  http://stackoverflow.com/questions/4611822/java-lang-outofmemoryerror-bitmap-size-exceeds-vm-budget
	 * @param view
	 */	
	protected  void unbindDrawables(View view) 
	{
		if (view == null)
			return;
		
		if (view.getBackground() != null)
		{
			view.getBackground().setCallback(null);
		}
        
		if (view instanceof ViewGroup) 
		{
			int count;
			ViewGroup viewGroup;
			
			viewGroup = (ViewGroup)view;			
			count = viewGroup.getChildCount();
			
			//Recursion
			for (int i = 0; i < count; i++) 
			{
				unbindDrawables(viewGroup.getChildAt(i));
			}

			if (view instanceof AdapterView)
			{
				//It is known that it is not support
			}
			else
				viewGroup.removeAllViews();
		}        
	}	
	
	@Override
	public void onBackPressed()
	{
		if (debugMode)
			TDStockLog.i(GetIdentity(), "Activity onBackPressed");
		SwitchBackActivity();
	}

	/** Set your activity to the top of the list.  If this is set, you have losen the list
	    and Switch Back should be malfunction **/
	protected void SetActivityToTop()
	{
		if (_activityController != null)
			_activityController.ActivityResetToTop(getClass());
	}

	/** Switch the display to the next Activity, using Forward action 
	  * @param iActivityClass - the activity that you want to switch to 
	  * @param iIntentObj - intent parameter
	  */
	protected void SwitchForwardActivity(
			Class<? extends Activity> iActivityClass, Intent iIntentObj)
	{
		if (_activityController != null)
			_activityController.ActivityForwardSwitch(this, iActivityClass,
					iIntentObj);
	}

	/** Switch the display to the next Activity, using Forward action
	  * @param iActivityClass - the activity that you want to switch to 
	  */
	protected void SwitchForwardActivity(
			Class<? extends Activity> iActivityClass)
	{
		SwitchForwardActivity(iActivityClass, new Intent());
	}

	/** Step one back from the list, usually switch to your last opened activity, using backward action **/
	protected void SwitchBackActivity()
	{
		if (_activityController != null)
			_activityController.ActivityBackwardSwitch(this);
	}

	/** Switch to iActivityClass using backward effect and make self window as the top of the list,
	  * erase other members in the list
	  * @param iActivityClass - the activity that you want to switch to 
	  */
	protected void SwitchBackwardToTop(Class<? extends Activity> iActivityClass)
	{
		SwitchBackwardToTop(iActivityClass, new Intent());
	}

	/** Switch to iActivityClass using backward effect and make self window as the top of the list,
	  * erase other members in the list,  bring in intent for switching *
	  *  @param iActivityClass - the activity that you want to switch to 
	  *  @param iIntentObj - intentObj, param you want for switch
	  */
	protected void SwitchBackwardToTop( Class<? extends Activity> iActivityClass, Intent iIntentObj)
	{
		if (_activityController != null)
			_activityController.ActivityBackwardSwitchToTop(this,
					iActivityClass, iIntentObj);
	}

	/** Switch to the iActivtyClass, let the system determine the direction of switching
	 *  @param iActivityClass - the activity that you want to switch to 
	 *  @param iIntentObj - intentObj, param you want for switching 
	 */
	protected void SwitchFreeActivity(
			Class<? extends Activity> iActivityClass, Intent iIntentObj)
	{
		if (_activityController != null)
			_activityController.ActivityFreeSwitch(this, iActivityClass, iIntentObj);
	}

	/** Switch to the iActivtyClass, let the system determine the direction of switching
	 *  @param iActivityClass - the activity that you want to switch to 
	 *  */
	protected void SwitchFreeActivity(Class<? extends Activity> iActivityClass)
	{
		SwitchFreeActivity(iActivityClass, new Intent());
	}

	/** Remove a particular class from the list
	 *  @param iActivityClass - the activity that you want to ignore
	 *  @return true for success, in some occasion, it would not allow you to remove the activity from the list
	 */
	protected boolean RemoveActivityFromList(Class<? extends Activity> iActivityClass)
	{
		if (_activityController == null)
			return false;

		return _activityController.ActivityRemoveFromList(iActivityClass);
	}
	
	/** Remove the item after the request activity, the request activity will not be removed
	 *  @param iActivityClass - the activity that want to be the last
	 *  @return true for success, in some occasion, it would not allow you to remove the activity from the list
	 */
	protected boolean RemoveAfterActivitysFromList(Class<? extends Activity> iActivityClass)
	{
		if (_activityController == null)
			return false;

		return _activityController.RemoveClassAfter(iActivityClass);
	}	
	
//	protected boolean ActivityReEnforce(Class<? extends Activity> iActivityClass)
//	{
//		if (_activityController == null)
//			return false;
//		
//		_activityController.ActivityReEnforce(this, iActivityClass, new Intent());
//		return true;
//	}
	

	/** Clear the Activity List, Alert: You are not suppose to, watch what you are doing **/
	protected void _ClearActivityList()
	{
		if (_activityController != null)
			_activityController.ActivityClearList();
	}

//	@Override
//	public boolean onKeyDown(int keyCode, KeyEvent event)
//	{
//		if (debugMode)
//			TDStockLog.i(GetIdentity(), "Activity onKeyDown:" + event.toString());
//
//		if (event.getAction() == KeyEvent.ACTION_DOWN)
//		{
//		    if (debugMode)
//			    TDStockLog.i(GetIdentity(), "onKeyDown: Code=" + keyCode);				
//			switch (keyCode)
//			{
//				case KeyEvent.KEYCODE_BACK:
//					onBackPressed();
//					return true;
//					// The Home key is not being used at his moment
//				case KeyEvent.KEYCODE_HOME:
//					onHomeKeyPressed();
//					return true;
//			}
//		}
//
//		return super.onKeyDown(keyCode, event);
//	}

	/** Create a unique id to be used for light streamer **/
	protected String LSGetUniqueID()
	{
		return GetIdentity() + String.valueOf(appHost.GetRunningIndex());
	}

	/** Check the existence of the identifier in our light streamer list **/
	protected boolean LightStreamerIsSubscribeItemExist(String iIdentifier)
	{
		int index;

		index = appHost.LSClient_GetIdentifierIndex(getClass(), iIdentifier);
		if (index == -1)
			return false;
		return true;
	}

	/** Subscribe the identifier items for light streamer, Payment Type is determined by the Application
	  * @param iIdentifier - unique ID out of the app, once way to obtain this ID is by using LSGetUniqueID or
	  *                      a static pre-defined string value that you only use once
	  * @param iItem - subscription item in the structure of LS_SubscriptionItem
	  * @param iResponse - the callback when data comes in
	  * @return true if successful
	  */
	protected boolean LightStreamerSubscribeItem(String iIdentifier,
			LS_SubscriptionItem iItem, ILS_UserClient_Response iResponse)
	{
		boolean status;
		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "LightStreamerSubscribeItem: " + iItem.toString());
		
		status = appHost.LSClient_SubscribeItem( getClass(), iIdentifier,
				                                 iItem, iResponse);
		
		//Check if it is fail because of a duplicate name
		if (status == false)
			status = LightStreamerIsSubscribeItemExist(iIdentifier);
		
		return status;
	}

	/** Subscribe the identifier items for light streamer, LS_ItemRequestType is used to determined the
	    payinfo type
	  * @param iIdentifier - unique ID out of the app, once way to obtain this ID is by using LSGetUniqueID or
	  *                      a static pre-defined string value that you only use once
	  * @param iItem - subscription item in the structure of LS_SubscriptionItem
	  * @param iSubscribeType - the payment type for this subscription, the system will not check again
	  * @param iResponse - the callback when data comes in
	  * @return true if successful	     
	  */
	protected boolean LightStreamerSubscribeItem(String iIdentifier, LS_SubscriptionItem iItem, LS_ItemRequestType iSubscribeType,
			ILS_UserClient_Response iResponse)
	{
		boolean status;
		
		if (debugMode)
			TDStockLog.i(GetIdentity(), "LightStreamerSubscribeItem: " + iItem.toString());
		
		status = appHost.LSClient_SubscribeItem(getClass(), iIdentifier,
				iItem, iSubscribeType, iResponse);
		
		//Check if it is fail because of a duplicate name
		if (status == false)
			status = LightStreamerIsSubscribeItemExist(iIdentifier);
		
		return status;
	}

	/** Subscribe the identifier items in a batch mode, send all at once, the size of each item must be the same.
	 * The linkage is as the sequence in the list
	 * @param iIdList - the list of unique item identifier for subscription
	 * @param iItemList - the list of item that you will subscribe
	 * @param iResponseList - the list of call back that you want for your information
	 * @return true if successful
	 */
	protected boolean LightStreamerSubscribeItemsInBatch( List<String> iIdList, List<LS_SubscriptionItem> iItemList, 
											    List<ILS_UserClient_Response> iResponseList)
	{
		if (iIdList.size() != iItemList.size())
			return false;
		
		if (iIdList.size() != iResponseList.size())
			return false;
				
		return appHost.LSClient_SubscribeListItems(getClass(), iIdList, iItemList, iResponseList);
	}
	
	/** Subscribe the identification items in batch mode, send all at once, the size of each item must be the same.
	 * The iRequestType is the same payment type for all groups subscription
	 * @param iIdList - the list of unique item identifier for subscription
	 * @param iItemList - the list of item that you will subscribe
	 * @param iRequestType - the payment that you are requesting, representing all members
	 * @param iResponseList - the list of call back that you want for your information
	 * @return true if successful
	 */
	protected boolean LightStreamerSubscribeItemInBatch( List<String> iIdList, List<LS_SubscriptionItem> iItemList,
											   LS_ItemRequestType iRequestType, List<ILS_UserClient_Response> iResponseList)
	{
		if (iIdList.size() != iItemList.size())
			return false;
		
		if (iIdList.size() != iResponseList.size())
			return false;
				
		return appHost.LSClient_SubscribeListItems(getClass(), iIdList, iItemList, iRequestType, iResponseList);
	}
	
	
	/** Subscribe the identifier items in a batch mode, send all at once, the size of each item must be the same.
	 * The linkage is as the sequence in the list
	 * @param iIdList - the list of unique item identifier for subscription
	 * @param iItemList - the list of item that you will subscribe
	 * @param iSubscribeTypeList - the list of the payment type, system will not check again 
	 * @param iResponseList - the list of call back that you want for your information
	 * @return true if successful
	 */	
	protected boolean LightStreamerSubscribeItemsInBatch( List<String> iIdList, List<LS_SubscriptionItem> iItemList,
				   							    List<LS_ItemRequestType> iSubscribeTypeList,
				   							    List<ILS_UserClient_Response> iResponseList)
	{
		if (iIdList.size() != iItemList.size())
			return false;

		if (iIdList.size() != iSubscribeTypeList.size())
			return false;
		
		if (iIdList.size() != iResponseList.size())
			return false;

		return appHost.LSClient_SubscribeListItems(getClass(), iIdList, iItemList, iSubscribeTypeList, iResponseList);
	}	
	
	
	/** Un-subscribe the identified item for this activity from light streamer
	  * @param iIdentifier - a defined ID that you have used in LightStreamerSubscribeItem
	  * @return true for success
	  */
	protected boolean LightStreamerUnsubscribeItem(String iIdentifier)
	{
		return appHost.LSClient_UnsubscribeItem(getClass(), iIdentifier);
	}

	/** To un-subscribe the light streamer items in batch mode
	 * Please note that only the existence list will be removed
	 * @param iIdList - list of the unique ID from the use of activity for light streamer
	 * @return
	 */
	protected boolean LightStreamerUnSubscribeItemsInBatch(List<String> iIdList)
	{
		return appHost.LSClient_UnsubscribeListItem(getClass(), iIdList);				
	}		
	
	/** Un-subscribe all the item on this Activity **/
	protected boolean LightStreamerUnsubscribeAll()
	{
		return appHost.LSClient_UnsubscribeAllItems(getClass());
	}

	/** Clear All the subscribe item belongs to this class
	 *  Since we only Un-subscribe on stop, this one should 
	 *  be run after the default onCreate of the instance
	 */
	protected void LSClient_FlushSafe()
	{
		appHost.LSClient_UnsubscribeAllItems(getClass());
	}
	
	/** This function is intended to use for temporary suspend
	 * LS items.  Design to be used when CDR is on time, and
	 * when this is called the CDR Ticker will start again(Add one-minute)
	 */
	protected boolean LS_ResumeAllItem()
	{
		return appHost.LSClient_ResumeAllItems(getClass());
	}
}
